﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data.Objects;
using System.Data.Entity.Infrastructure;

namespace CustomerService
{
    public partial class EditCustomer : System.Web.UI.Page
    {
        private SalesManagerEntities _sme;
        private tblCustomer _customer = null;
        private int _customerID;
        protected tblOwner _owner;

        protected void Page_Load(object sender, EventArgs e)
        {
            _sme = (SalesManagerEntities)Session["sme"];
            if (_sme == null)
            {
                Response.Redirect("default.aspx");
                return;
            }
            int.TryParse(Request.QueryString["CustomerID"], out _customerID);
            if (!IsPostBack)
            {
                SqlConnection conn = (SqlConnection)_sme.Database.Connection;
                if (conn.State != System.Data.ConnectionState.Open )
                    conn.Open();
                SqlCommand cmm = conn.CreateCommand();

                cmm.CommandText = "exec spLoadCustomer @CustomerID";
                cmm.Parameters.Add(new SqlParameter("@CustomerID", _customerID));
                SqlDataReader rdr = cmm.ExecuteReader();

                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblAddress>(rdr, "SalesManagerEntities.tblAddress", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblPerson>(rdr, "SalesManagerEntities.tblPerson", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<codeContactPointType>(rdr, "SalesManagerEntities.codeContactPointType", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                _customer = ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblCustomer>(rdr, "SalesManagerEntities.tblCustomer", MergeOption.PreserveChanges).FirstOrDefault();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblContactPoint>(rdr, "SalesManagerEntities.tblContactPoint", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<codeHoldReason>(rdr, "SalesManagerEntities.codeHoldReason", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblOrderSource>(rdr, "SalesManagerEntities.tblOrderSource", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblPromotion>(rdr, "SalesManagerEntities.tblPromotion", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblOrderHeader>(rdr, "SalesManagerEntities.tblOrderHeader", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblProduct>(rdr, "SalesManagerEntities.tblProduct", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblOrderDetail>(rdr, "SalesManagerEntities.tblOrderDetail", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequence>(rdr, "SalesManagerEntities.tblSequence", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequenceOrder>(rdr, "SalesManagerEntities.tblSequenceOrder", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequenceStep>(rdr, "SalesManagerEntities.tblSequenceStep", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequenceStepProduct>(rdr, "SalesManagerEntities.tblSequenceStepProduct", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequenceOrderStep>(rdr, "SalesManagerEntities.tblSequenceOrderStep", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblSequenceOrderStepProduct>(rdr, "SalesManagerEntities.tblSequenceOrderStepProduct", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblRefund>(rdr, "SalesManagerEntities.tblRefund", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblRMAReturn>(rdr, "SalesManagerEntities.tblRMAReturn", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblReturnDetail>(rdr, "SalesManagerEntities.tblReturnDetail", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblTransaction>(rdr, "SalesManagerEntities.tblTransaction", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblTransactionSubmit>(rdr, "SalesManagerEntities.tblTransactionSubmit", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblAccount>(rdr, "SalesManagerEntities.tblAccount", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblTransactionSubmit>(rdr, "SalesManagerEntities.tblTransactionSubmit", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblMiscDef>(rdr, "SalesManagerEntities.tblMiscDef", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblInventory>(rdr, "SalesManagerEntities.tblInventory", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblInventoryTransaction>(rdr, "SalesManagerEntities.tblInventoryTransactions", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblInventoryTransactionDetail>(rdr, "SalesManagerEntities.tblInventoryTransactionDetail", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblPackage>(rdr, "SalesManagerEntities.tblPackages", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblAltOrderID>(rdr, "SalesManagerEntities.tblAltOrderID", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblAltCustomerID>(rdr, "SalesManagerEntities.tblAltCustomerID", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblNote>(rdr, "SalesManagerEntities.tblNote", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblCustomerNote>(rdr, "SalesManagerEntities.tblCustomerNote", MergeOption.PreserveChanges).Count();
                rdr.NextResult();
                ((IObjectContextAdapter)_sme).ObjectContext.Translate<tblOrderNote>(rdr, "SalesManagerEntities.tblOrderNote", MergeOption.PreserveChanges).Count();
                // Load the selcted customer from the database
                //IQueryable<tblCustomer> oq =
                //    from c in _sme.tblCustomer
                //        .Include("Person")
                //        .Include("Person.Address")
                //        .Include("Person.Address.Country")
                //        .Include("Person.Language")
                //        .Include("Person.ContactPoints")
                //        .Include("Person.ContactPoints.ContactPointType")
                //        .Include("OrderHeaders")
                //        .Include("OrderHeaders.ShipTo_Person")
                //        .Include("OrderHeaders.ShipTo_Address")
                //        .Include("OrderHeaders.ShipTo_Address.Country")
                //        .Include("OrderHeaders.HoldReason")
                //        .Include("OrderHeaders.OrderSource")
                //        .Include("OrderHeaders.OrderType")
                //        .Include("OrderHeaders.OrderStatus")
                //        .Include("OrderHeaders.OrderDetails")
                //        .Include("OrderHeaders.OrderDetails.Product")
                //        .Include("OrderHeaders.SequenceOrders.SequenceSteps.Sequence")
                //    where c.CustomerID == _customerID
                //    select c;
                ////string t = ((System.Data.Objects.ObjectQuery)oq).ToTraceString();
                //_customer = oq.First(f => f.CustomerID == _customerID);
            }
            else
                _customer = _sme.tblCustomer.Find(new object[] {_customerID});

            OwnerEntities oe = new OwnerEntities();
            _owner = oe.tblOwner.Find(new object[] { _customer.OwnerID });

            Load();
        }

        protected new void Load()
        {
            // Load the form from the database
            ((CustomerTab)TabContainer1.FindControl("TabPanelCustomer").FindControl("customerTab1")).Load(_sme, _customer); 
            ((OrderTab)TabContainer1.FindControl("TabPanelOrders").FindControl("orderTab1")).Load(_sme, _customer);
            ((SequenceTab)TabContainer1.FindControl("TabPanelSequences").FindControl("sequenceTab1")).Load(_sme, _customer);
            ((TransactionsTab)TabContainer1.FindControl("TabPanelTransactions").FindControl("transactionsTab1")).Load(_sme, 
                _sme.tblTransaction.Local.Where(p=>p.OrderHeader.CustomerID == _customer.CustomerID).OrderByDescending(c=>c.CreateDate));
            ((CustomerSourceIDTab)TabContainer1.FindControl("tabPanelCustomerSourceID").FindControl("customerSourceIDsTab1")).Load(_sme,
                _sme.tblAltCustomerID.Local.Where(p => p.CustomerID == _customer.CustomerID));
            ((tabNotes)TabContainer1.FindControl("TabPanelNotes").FindControl("notesTab1")).Load(_sme, _customer);
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            Page.Validate();
            if (!Page.IsValid)
                return;
            lblMessage.Text = string.Empty;

            if (string.IsNullOrEmpty(txtNote.Text))
            {
                if (!Page.ClientScript.IsStartupScriptRegistered("EnterNote"))
                    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "EnterNote",
                        "<script  language='javascript' type='text/javascript'>" +
                        "alert('Please enter a note before saving changes.');" +
                        "</script>"
                        );
                return;
            }

            // Save the note.
            tblNote note;
            if (Session["Note"] != null)
                note = (tblNote)Session["Note"];
            else
            {
                // Create a new note
                note = new tblNote();
                note.AgentID = _sme.UserID();
                _sme.tblNote.Add(note);
                Session["Note"] = note;

                // Tie the note to the customer
                tblCustomerNote customerNote = new tblCustomerNote();
                customerNote.Note = note;
                customerNote.Customer = _customer;
                _sme.tblCustomerNote.Add(customerNote);

                // See if we can find any orders to tie the note to.
                SortedSet<int> orderIdList = new SortedSet<int>();
                foreach (DbEntityEntry entry in _sme.ChangeTracker.Entries().Where(c => c.State == System.Data.EntityState.Added || c.State == System.Data.EntityState.Modified))
                {
                    if (entry.CurrentValues.PropertyNames.Contains("OrderID"))
                        if (entry.Property("OrderID").CurrentValue != null && !orderIdList.Contains((int)entry.Property("OrderID").CurrentValue))
                            orderIdList.Add((int)entry.Property("OrderID").CurrentValue);
                }
                foreach (int orderID in orderIdList)
                {
                    tblOrderNote orderNote = new tblOrderNote();
                    orderNote.Note = note;
                    orderNote.OrderHeader = _sme.tblOrderHeader.Find(new object[] { orderID });
                    if (orderNote.OrderHeader != null)
                        _sme.tblOrderNote.Add(orderNote);
                }
            }
            note.NoteText = txtNote.Text;

            try
            {
                _sme.SaveAllChanges(_customerID);
            }
            catch (Exception err)
            {
                string message = "Error saving customer<br />" + err.Message;
                while (err.InnerException != null)
                {
                    err = err.InnerException;
                    message += "<br />" + err.Message;
                }
                AddCustomerError(message);
            }

            ValidatePaymentInfo();

            Load();
        }


        // Save changes and authorize the credit card.
        protected void btnAuthCard_Click(object sender, EventArgs e)
        {
            Page.Validate();
            if (!Page.IsValid)
                return;
            lblMessage.Text = string.Empty;

            // Validate that payment info has been entered
            if (!ValidatePaymentInfo())
                return;

            // Save changes to the customer
            try
            {
                _sme.SaveAllChanges(_customerID);
            }
            catch (Exception err)
            {
                string message = "Error saving customer<br />" + err.Message;
                while (err.InnerException != null)
                {
                    err = err.InnerException;
                    message += "<br />" + err.Message;
                }
                AddCustomerError(message);
                return;
            }

            return;

            // Look for orders to authorize
            foreach (tblOrderHeader oh in _customer.OrderHeaders.Where(o => o.OrderStatusCode == "P" && o.OrderTotal > 0 && o.tblAccount != null))
            {
                // Make sure the order does not already have an authorized or depositted transaction for it.
                if (oh.Transactions.Where(c=>c.TransactionTypeCode == "B" && 
                        (c.TransactionStatusCode == "A" || c.TransactionStatusCode == "I" )).Count() == 0)
                {
                    // Look for an existing pending transaction
                    tblTransaction transaction = oh.Transactions.Where(c=>c.TransactionTypeCode == "B" && c.TransactionStatusCode == "E" ).FirstOrDefault();

                    // If not transaction exists then create the payment transaction
                    if (transaction == null)
                    {
                        transaction = new tblTransaction();
                        transaction.OrderHeader = oh;
                        transaction.tblAccount = oh.tblAccount;
                        transaction.ProcessorCode = oh.ProcessorCode;
                        transaction.Amount = oh.OrderTotal;
                        transaction.TransactionType = _sme.codeTransactionType.Find(new object[] {"B"});
                        transaction.TransactionStatus = _sme.codeTransactionStatus.Find(new object[] {"E"});
                        transaction.CreateDate = DateTime.Now;

                        _sme.tblTransaction.Add(transaction);
                        _sme.SaveChanges();
                    }

                    OnlinePayments.PaymentProcessor.AuthorizeTransaction(
                        (SqlConnection)_sme.Database.Connection,
                        transaction.TransactionID, null);

                    // Reload the transaction and transaction submissions.
                    _sme.Entry<tblTransaction>(transaction).Reload();
                    (from c in _sme.tblTransactionSubmit where c.TransactionID == transaction.TransactionID select c).Count();
                }
            }
            
        }

        bool ValidatePaymentInfo()
        {
            // Validate that orders are complete.
            if (_customer.OrderHeaders.Where(o => o.OrderStatusCode == "P" && o.OrderTotal > 0 && o.tblAccount == null).Count() > 0)
            {
                AddCustomerError("A pending order has been entered with no payment information.");
                return false;
            }

            // Validate the card expiration dates.
            foreach (tblOrderHeader oh in _customer.OrderHeaders.Where(o => o.OrderStatusCode == "P" && o.OrderTotal > 0 && o.tblAccount != null))
            {
                try
                {
                    DateTime dt = DateTime.ParseExact(oh.tblAccount.CardExpiration, "MMyy", System.Globalization.CultureInfo.CurrentCulture);
                    if (dt.AddMonths(1) < DateTime.Now)
                    {
                        AddCustomerError("A card expiration is past due.  Please get updated payment from the customer.");
                        return false;
                    }

                    if (Convert.IsDBNull(oh.ProcessorCode))
                    {
                        AddCustomerError("The PaymentProcessorCode is not set.");
                        return false;
                    }
                }
                catch (Exception)
                {
                }
            }

            return true;
        }

        private void AddCustomerError(string str)
        {
            lblMessage.Text += str + "<br />";
        }

        protected void btnHome_Click(object sender, EventArgs e)
        {
            if (_sme.ChangeTracker.Entries().Any(c=>c.State == System.Data.EntityState.Added || c.State == System.Data.EntityState.Deleted || c.State == System.Data.EntityState.Modified))
            {
                IEnumerable<DbEntityEntry> changes = _sme.ChangeTracker.Entries().Where(c => c.State == System.Data.EntityState.Added || c.State == System.Data.EntityState.Deleted || c.State == System.Data.EntityState.Modified);
                if (!Page.ClientScript.IsStartupScriptRegistered("VerifyHome"))
                {
                    Page.ClientScript.RegisterStartupScript(this.GetType(), "VerifyHome",
                        "<script  language='javascript' type='text/javascript'>" +
                        "if (confirm('Are you sure you want to discard all changes?') == true)\n" +
                        "   __doPostBack('" + btnDiscard.ClientID + "', '');" +
                        "</script>"
                        );
                }
            }
            else
                Response.Redirect("Default.aspx");
        }

        protected override void Render(HtmlTextWriter writer)
        {
            Page.ClientScript.RegisterForEventValidation(btnDiscard.ClientID);

            base.Render(writer);
        }

        protected void btnDiscard_Click(object sender, EventArgs e)
        {
            Session["sme"] = null;
            Response.Redirect("Default.aspx");
        }
    }
}
